从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?从前有座山,山里有座庙,庙里有个老和尚,正在给小和尚讲故事呢!故事是什么呢?……

    野比大雄在房间里,用时光电视看着未来的情况。电视画面中,野比大雄在房间里,用时光电视看着未来的情况。电视画面中,野比大雄在房间里,用时光电视看着未来的情况……

    阶乘的递归定义:0! = 1n!=n*(n-1)! ,使用被定义对象的自身来为其下定义称为递归定义。

    是递归的一种视觉形式。图中女性手持的物体中有一幅她本人手持同一物体的小图片,进而小图片中还有更小的一幅她手持同一物体的图片……

    在程序中,一个函数如果直接或者间接的调用了自身,我们就称之为递归函数。

    写递归函数有两个要点:

    1. 收敛条件 - 什么时候结束递归。
    2. 递归公式 - 每一项与前一项(前N项)的关系。

    Python对递归的深度加以了限制(默认1000层函数调用),如果想突破这个限制,可以使用下面的方法。

    1. sys.setrecursionlimit(10000)

    例子2:爬楼梯 - 楼梯有n个台阶,一步可以走1阶、2阶或3阶,走完n个台阶共有多少种不同的走法。

    注意:上面的递归函数性能会非常的差,因为时间复杂度是几何级数级的。

    优化后的代码。

    1. from functools import lru_cache
    2. @lru_cache()
    3. def climb(num):
    4. if num == 0:
    5. return 1
    6. elif num < 0:
    7. return 0
    8. return climb(num - 1) + climb(num - 2) + climb(num - 3)

    不使用的递归的代码。

    重点:有更好的办法的时候,请不要考虑递归。

    回溯法暴力搜索法中的一种。对于某些计算问题而言,回溯法是一种可以找出所有(或一部分)解的一般性算法,尤其适用于约束满足问题(在解决约束满足问题时,我们逐步构造更多的候选解,并且在确定某一部分候选解不可能补全成正确解之后放弃继续搜索这个部分候选解本身及其可以拓展出的子候选解,转而测试其他的部分候选解)。

    算法入门系列2 - 在水一方 - 图1

    1. """
    2. 迷宫寻路
    3. """
    4. import random
    5. import sys
    6. WALL = -1
    7. ROWS = 10
    8. COLS = 10
    9. def find_way(maze, i=0, j=0, step=1):
    10. """走迷宫"""
    11. if 0 <= i < ROWS and 0 <= j < COLS and maze[i][j] == 0:
    12. maze[i][j] = step
    13. if i == ROWS - 1 and j == COLS - 1:
    14. print('=' * 20)
    15. display(maze)
    16. sys.exit(0)
    17. find_way(maze, i + 1, j, step + 1)
    18. find_way(maze, i, j + 1, step + 1)
    19. find_way(maze, i - 1, j, step + 1)
    20. find_way(maze, i, j - 1, step + 1)
    21. maze[i][j] = ROAD
    22. def reset(maze):
    23. """重置迷宫"""
    24. for i in range(ROWS):
    25. for j in range(COLS):
    26. num = random.randint(1, 10)
    27. maze[i][j] = WALL if num > 7 else ROAD
    28. def display(maze):
    29. """显示迷宫"""
    30. for row in maze:
    31. for col in row:
    32. if col == -1:
    33. print('■', end=' ')
    34. elif col == 0:
    35. print('□', end=' ')
    36. else:
    37. print(f'{col}'.ljust(2), end='')
    38. print()
    39. def main():
    40. """主函数"""
    41. maze = [[0] * COLS for _ in range(ROWS)]
    42. reset(maze)
    43. display(maze)
    44. find_way(maze)
    45. print('没有出路!!!')
    46. main()

    说明:上面的代码用随机放置围墙的方式来生成迷宫,更好的生成迷宫的方式请参考一文。

    例子2:骑士巡逻 - 国际象棋中的骑士(马),按照骑士的移动规则走遍整个棋盘的每一个方格,而且每个方格只能够经过一次。

    例子3:八皇后 - 如何能够在8×8的国际象棋棋盘上放置八个皇后,使得任何一个皇后都无法直接吃掉其他的皇后?为了达到此目的,任两个皇后都不能处于同一条横行、纵行或斜线上。

    算法入门系列2 - 在水一方 - 图2

    说明:这个问题太经典了,网上有大把的答案,留给大家自己搞定。